<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xeokit Example</title>
    <link href="../css/pageStyle.css" rel="stylesheet"/>
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
    <style>

        /* ----------------------------------------------------------------------------------------------------------*/
        /* NavCubePlugin */
        /* ----------------------------------------------------------------------------------------------------------*/

        #myNavCubeCanvas {
            position: absolute;
            width: 250px;
            height: 250px;
            bottom: 50px;
            right: 10px;
            z-index: 200000;
        }

        /* ----------------------------------------------------------------------------------------------------------*/
        /* TreeViewPlugin */
        /* ----------------------------------------------------------------------------------------------------------*/

        #treeViewContainer {
            pointer-events: all;
            height: calc(100% - 80px);
            overflow-y: scroll;
            overflow-x: hidden;
            position: absolute;
            background-color: rgba(255, 255, 255, 0.2);
            color: black;
            top: 80px;
            z-index: 200000;
            float: left;
            left: 0;
            padding-left: 16px;
            font-family: 'Roboto', sans-serif;
            font-size: 15px;
            user-select: none;
            -ms-user-select: none;
            -moz-user-select: none;
            -webkit-user-select: none;
            width: 450px;
        }

        #treeViewContainer button, 
        #treeViewContainer input {
            background-color: transparent;
            border-style: none;
        }

        #treeViewContainer ul {
            list-style: none;
            padding-left: 18px;
        }

        #treeViewContainer ul li div {
            padding-left: 8px;
            height: 40px;
            width: 100%;
            display: flex;
            align-items: center;
        }
        
        #treeViewContainer ul li div.v-treeview-node__level{
            width: 24px;
            display: inline-flex;
        }

        #treeViewContainer ul li button {
            display: inline-flex;
        }
        
        #treeViewContainer ul li input {
            margin-left: 4px;
            margin-right: 4px;
            width: 18px;
            height: 18px;
        }

        #treeViewContainer ul li input[type=checkbox] {
            position: relative;
            cursor: pointer;
        }

        #treeViewContainer ul li input[type=checkbox]:before {
            content: "";
            display: block;
            position: absolute;
            width: 20px;
            height: 20px;
            top: 0;
            left: 0;
            border: 2px solid rgba(0, 0, 0, 0.54);
            border-radius: 3px;
            background-color:#fff;
        }

        #treeViewContainer ul li input[type=checkbox]:checked:before {
            content: "";
            display: block;
            position: absolute;
            width: 20px;
            height: 20px;
            top: 0;
            left: 0;
            border: 2px solid #398684;
            background-color: #398684 !important;
        }
        #treeViewContainer ul li input[type=checkbox]:checked:after {
            content: "";
            display: block;
            width: 8px;
            height: 12px;
            border: solid white;
            border-width: 0 2px 2px 0;
            -webkit-transform: rotate(45deg);
            -ms-transform: rotate(45deg);
            transform: rotate(45deg);
            position: absolute;
            top: 2px;
            left: 6px;
        }
        
        #treeViewContainer ul li span {
            vertical-align: middle;
            margin-left: 6px;
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;
            flex: 1;
        }

        .v-icon {
            align-items: center;
            display: inline-flex;
            font-feature-settings: "liga";
            height: 1em;
            justify-content: center;
            letter-spacing: normal;
            line-height: 1;
            position: relative;
            text-indent: 0;
            text-align: center;
            user-select: none;
            vertical-align: middle;
            width: 1em;
            min-width: 1em;
            font-size: 1.5em;
            cursor: pointer;
        }
        .v-ifcicon {
            margin-left: 6px;
            font-size: 1.5em;
            color: #398684;
        }

    </style>
</head>
<body>
<input type="checkbox" id="info-button"/>
<label for="info-button" class="info-button"><i class="far fa-3x fa-question-circle"></i></label>
<canvas id="myCanvas"></canvas>
<canvas id="myNavCubeCanvas"></canvas>
<div id="treeViewContainer"></div>
<div class="slideout-sidebar">
    <img class="info-icon" src="../../assets/images/tree_view_icon.png"/>
    <h1>TreeViewPlugin</h1>
    <h2>IFC Containment Hierarchy</h2>
    <h3>Stats</h3>
    <ul>
        <li>
            <div id="time">Loading JavaScript modules...</div>
        </li>
    </ul>
    <h3>Components used</h3>
    <ul>
        <li>
            <a href="../../docs/class/src/viewer/Viewer.js~Viewer.html"
               target="_other">Viewer</a>
        </li>
        <li>
            <a href="../../docs/class/src/plugins/XKTLoaderPlugin/XKTLoaderPlugin.js~XKTLoaderPlugin.html"
               target="_other">XKTLoaderPlugin</a>
        </li>
        <li>
            <a href="../../docs/class/src/plugins/TreeViewPlugin/TreeViewPlugin.js~TreeViewPlugin.html"
               target="_other">TreeViewPlugin</a>
        </li>
        <li>
            <a href="../../docs/class/src/plugins/NavCubePlugin/NavCubePlugin.js~NavCubePlugin.html"
               target="_other">NavCubePlugin</a>
        </li>
    </ul>
    <h3>Resources</h3>
    <ul>
        <ul>
            <li><a href="https://help.autodesk.com/view/RVT/2023/ENU/?guid=GUID-61EF2F22-3A1F-4317-B925-1E85F138BE88" target="_other">Model source</a></li>
        </ul>
    </ul>
</div>
</body>

<script type="module">

    // see: https://pictogrammers.com/library/mdi/
    const ifcIcons = {
        "IfcProject": "mdi-file-cad",
        "IfcSite": "mdi-earth",
        "IfcBuilding": "mdi-office-building",
        "IfcBuildingStorey": "mdi-menu",
        "IfcDoor": "mdi-door",
        "IfcWindow": "mdi-window-closed-variant",
        "IfcAirTerminal": "mdi-weather-windy",
        "IfcLamp": "mdi-lightbulb",
        "IfcLightFixture": "\uf02a",
        "IfcSpace": "mdi-lamp",
        "IfcCurtainWall": "mdi-wall",
        "IfcWall": "mdi-wall",
        "IfcWallStandardCase": "mdi-wall",
        "IfcSlab": "mdi-border-bottom",
        "IfcPlate": "mdi-border-bottom",
        "IfcFurniture": "mdi-sofa",
        "IfcFurnishingElement": "mdi-sofa",
        "IfcSystemFurnitureElement": "mdi-sofa",
        "IfcOpeningElement": "mdi-square-outline",
        "IfcProduct": "mdi-square",
        "IfcGrid": "mdi-grid",
        "IfcPort": "mdi-ev-plug-type2",
        "IfcCivilElement": "mdi-forest",
        "IfcGeographicElement": "mdi-forest",
        "IfcBeam": "mdi-drag-vertical-variant",
        "IfcColumn": "mdi-border-vertical",
        "IfcSpaceHeater": "mdi-thermometer-lines",
        "IfcRoof": "mdi-home-roof",
        "IfcFooting": "mdi-warehouse",
        "IfcRailing": "mdi-fence",
        "IfcStair": "mdi-stairs-box",
        "IfcStairFlight": "mdi-stairs-box",
        "IfcTransportElement": "mdi-elevator-passenger",
        "IfcLinearElement": "mdi-chart-timeline-variant",
        "IfcAnnotation": "mdi-message-alert-outline",
        "IfcElementAssembly": "mdi-land-plots",
        "IfcRamp": "mdi-triangle-outline",
        "IfcRampFlight": "mdi-triangle-outline",
        "IfcBuildingElementProxy": "mdi-help",
        "IfcBuildingElementPart": "mdi-land-plots",
        "IfcSensor": "mdi-access-point",
        "IfcSanitaryTerminal": "mdi-bathtub-outline",
        "IfcAudioVisualAppliance": "mdi-television",
    };

    const treeRender = {
        createRootNode: () => {
            return document.createElement('ul')
        },
        createNodeElement: (node, expandHandler, checkHandler, contextmenuHandler, titleClickHandler) => {
            const nodeElement = document.createElement('li');
            nodeElement.id = node.nodeId;

            if (node.xrayed) {
                nodeElement.classList.add('xrayed-node');
            }

            const wrapperDiv = document.createElement('div');
            nodeElement.appendChild(wrapperDiv);

            if (node.children.length > 0) {
                const switchElement = document.createElement('button');
                switchElement.id = `sw-${node.nodeId}`;
                switchElement.classList.add('v-icon', 'mdi', 'mdi-menu-right');
                if (expandHandler) switchElement.addEventListener('click', expandHandler);
                wrapperDiv.appendChild(switchElement);
            } else {
                const divElement = document.createElement('div');
                divElement.classList.add('v-treeview-node__level');
                wrapperDiv.appendChild(divElement);
            }
            
            const checkbox = document.createElement('input');
            checkbox.id = `cb-${node.nodeId}`;
            checkbox.type = "checkbox";
            checkbox.checked = node.checked;
            checkbox.style.pointerEvents = 'all';
            if (checkHandler) checkbox.addEventListener("change", checkHandler);
            wrapperDiv.appendChild(checkbox);

            const iconType = ifcIcons[node.type];
            if (iconType) {
                const icon = document.createElement('i');
                icon.classList.add('v-ifcicon', 'mdi', iconType);
                icon.title = node.type;
                wrapperDiv.appendChild(icon);
            } else {
                console.warn(`No icon for type ${node.type}`);
            }
            
            const span = document.createElement('span');
            span.textContent = node.title;
            wrapperDiv.appendChild(span);

            if (contextmenuHandler) {
                span.oncontextmenu = contextmenuHandler;
            }

            if (titleClickHandler) {
                span.onclick = titleClickHandler;
            }

            return nodeElement;
        },
        createDisabledNodeElement: (rootName) => {
            const li = document.createElement('li');

            const switchElement = document.createElement('a');
            switchElement.href = '#';
            switchElement.textContent = '!';
            switchElement.classList.add('warn');
            switchElement.classList.add('warning');
            li.appendChild(switchElement);
            
            const span = document.createElement('span');
            span.textContent = rootName;
            li.appendChild(span);

            return li;
        },
        addChildren: (element, nodes) => {
            const ul = document.createElement('ul');
            nodes.forEach((nodeElement) => {
            ul.appendChild(nodeElement);
            });

            element.parentElement.parentElement.appendChild(ul);
        },
        expand: (element, expandHandler, collapseHandler) => {
            element.classList.remove('mdi-menu-right');
            element.classList.add('mdi-menu-down');
            element.removeEventListener('click', expandHandler);
            element.addEventListener('click', collapseHandler);
        },
        collapse: (element, expandHandler, collapseHandler) => {
            if (!element) {
            return;
            }
            const parent = element.parentElement.parentElement;
            if (!parent) {
                return;
            }
            const ul = parent.querySelector('ul');
            if (!ul) {
                return;
            }
            parent.removeChild(ul);
            element.classList.remove('mdi-menu-down');
            element.classList.add('mdi-menu-right');
            element.removeEventListener('click', collapseHandler);
            element.addEventListener('click', expandHandler);
        },
        isExpanded: (element) => {
            const parentElement = element.parentElement.parentElement;
            return parentElement.getElementsByTagName('li')[0] !== undefined;
        },
        getId: (element) => {
            const parentElement = element.parentElement.parentElement;
            return parentElement.id;
        },
        getIdFromCheckbox: (element) => {
            return element.id.replace('cb-', '');
        },
        getSwitchElement: (nodeId) => {
            return document.getElementById(`sw-${nodeId}`);
        },
        isChecked: (element) => {
            return element.checked;
        },
        setCheckbox: (nodeId, checked, indeterminate) => {
            const checkbox = document.getElementById(`cb-${nodeId}`);
            if (checkbox) {
                if (checked !== checkbox.checked) {
                    checkbox.checked = checked;
                }
                if (indeterminate !== checkbox.indeterminate) {
                    checkbox.indeterminate = indeterminate;
                }
            }
        },
        setXRayed: (nodeId, xrayed) => {
            // not implemented
        },
        setHighlighted: (nodeId, highlighted) => { 
            // not implemented
        }
    };

    //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {Viewer, XKTLoaderPlugin, NavCubePlugin, TreeViewPlugin} from "../../dist/xeokit-sdk.min.es.js";

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer, arrange the camera, tweak x-ray and highlight materials
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true,
        dtxEnabled: true
    });

    const cameraControl = viewer.cameraControl;
    const scene = viewer.scene;
    const cameraFlight = viewer.cameraFlight;

    cameraControl.followPointer = true;
    cameraFlight.duration = 1.0;
    cameraFlight.fitFOV = 25;

    viewer.scene.camera.eye = [-37.1356047775136, 13.019223731456176, 58.51748229729708];
    viewer.scene.camera.look = [-21.930914776596467, 1.3515918520952024, 29.454670463302506];
    viewer.scene.camera.up = [0.15536164462465452, 0.9421651211030125, -0.2969640448883814];

    viewer.scene.xrayMaterial.fillAlpha = 0.1;
    viewer.scene.xrayMaterial.fillColor = [0, 0, 0];
    viewer.scene.xrayMaterial.edgeAlpha = 0.4;
    viewer.scene.xrayMaterial.edgeColor = [0, 0, 0];

    viewer.scene.highlightMaterial.fillAlpha = 0.3;
    viewer.scene.highlightMaterial.edgeColor = [1, 1, 0];

    //------------------------------------------------------------------------------------------------------------------
    // Create a NavCube
    //------------------------------------------------------------------------------------------------------------------

    new NavCubePlugin(viewer, {
        canvasId: "myNavCubeCanvas",
        visible: true,
        size: 250,
        alignment: "bottomRight",
        bottomMargin: 100,
        rightMargin: 10
    });

    //------------------------------------------------------------------------------------------------------------------
    // Create an IFC structure tree view
    //------------------------------------------------------------------------------------------------------------------

    new TreeViewPlugin(viewer, {
        containerElement: document.getElementById("treeViewContainer"),
        autoExpandDepth: 3, // Initially expand tree three storeys deep
        hierarchy: "containment",
        renderService: treeRender
    });

    //----------------------------------------------------------------------------------------------------------------------
    // Load a model and fit it to view
    //----------------------------------------------------------------------------------------------------------------------

    const xktLoader = new XKTLoaderPlugin(viewer);

    const sceneModel = xktLoader.load({
        id: "Widget",
        src: "../../assets/models/xkt/v10/ifc/rac.xkt",
        edges: true,
        excludeUnclassifiedObjects: false
    });


    const t0 = performance.now();
    document.getElementById("time").innerHTML = "Loading model...";
    sceneModel.on("loaded", function () {
        const t1 = performance.now();
        document.getElementById("time").innerHTML = "Model loaded in " + Math.floor(t1 - t0) / 1000.0 + " seconds<br>Objects: " + sceneModel.numEntities;
    });



</script>
</html>
